package com.gzc.just.play.last.war.sceneserver.network.broadcast;

import com.google.protobuf.Message;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.List;

/**
 * TCP消息广播器 - 用于TCP网络消息广播
 * 
 * 映射自C++ SSBattle::BroadMsgToGC 等广播方法
 * 通过TCP连接向GateServer转发消息
 * 
 * @author AI编程助手
 * @version 1.0
 */
public class MessageBroadcaster {
    
    private final String broadcasterId;
    private final BroadcastQueue broadcastQueue;
    private final Map<Long, BattlePlayerConnection> playerConnections = new ConcurrentHashMap<>();
    private final AtomicBoolean running = new AtomicBoolean(false);
    
    // 广播统计
    private volatile long totalBroadcasted = 0;
    private volatile long failedCount = 0;
    
    // 监听器
    private final List<BroadcasterListener> listeners = new CopyOnWriteArrayList<>();
    
    /**
     * 构造函数
     * 
     * @param broadcasterId 广播器ID
     * @param maxQueueSize 最大队列容量
     */
    public MessageBroadcaster(String broadcasterId, int maxQueueSize) {
        this.broadcasterId = broadcasterId;
        this.broadcastQueue = new BroadcastQueue(maxQueueSize);
    }
    
    /**
     * 启动广播器
     */
    public void start() {
        if (running.compareAndSet(false, true)) {
            startBroadcastThread();
        }
    }
    
    /**
     * 停止广播器
     */
    public void stop() {
        running.set(false);
    }
    
    /**
     * 启动广播线程
     */
    private void startBroadcastThread() {
        Thread broadcastThread = new Thread(() -> {
            while (running.get()) {
                try {
                    // 从队列获取消息并广播
                    BroadcastMessage message = broadcastQueue.dequeue();
                    if (message != null) {
                        broadcastToTargets(message);
                    } else {
                        // 队列为空，等待
                        Thread.sleep(10);
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                } catch (Exception e) {
                    notifyError(e);
                }
            }
        });
        broadcastThread.setName("BroadcastThread-" + broadcasterId);
        broadcastThread.setDaemon(true);
        broadcastThread.start();
    }
    
    /**
     * 广播消息到战斗中的所有玩家
     * 
     * @param battleId 战斗ID
     * @param message Protobuf消息
     * @param messageTypeId 消息类型ID
     * @return 是否入队成功
     */
    public boolean broadcastToAllPlayers(long battleId, Message message, int messageTypeId) {
        BroadcastMessage broadcastMsg = new BroadcastMessage(
                battleId,
                BroadcastMessage.BroadcastType.BROADCAST_TO_BATTLE,
                message,
                messageTypeId
        );
        return broadcastQueue.enqueue(broadcastMsg);
    }
    
    /**
     * 广播消息到特定队伍
     * 
     * @param battleId 战斗ID
     * @param teamId 队伍ID
     * @param message Protobuf消息
     * @param messageTypeId 消息类型ID
     * @return 是否入队成功
     */
    public boolean broadcastToTeam(long battleId, int teamId, Message message, int messageTypeId) {
        BroadcastMessage broadcastMsg = new BroadcastMessage(
                battleId,
                BroadcastMessage.BroadcastType.BROADCAST_TO_TEAM,
                message,
                messageTypeId
        );
        broadcastMsg.setTeamId(teamId);
        return broadcastQueue.enqueue(broadcastMsg);
    }
    
    /**
     * 发送消息给特定玩家
     * 
     * @param battleId 战斗ID
     * @param playerId 玩家ID
     * @param message Protobuf消息
     * @param messageTypeId 消息类型ID
     * @return 是否入队成功
     */
    public boolean sendToPlayer(long battleId, long playerId, Message message, int messageTypeId) {
        BroadcastMessage broadcastMsg = new BroadcastMessage(
                battleId,
                BroadcastMessage.BroadcastType.SEND_TO_PLAYER,
                message,
                messageTypeId
        );
        broadcastMsg.setTargetPlayerId(playerId);
        return broadcastQueue.enqueue(broadcastMsg);
    }
    
    /**
     * 将消息广播到目标
     * 
     * @param message 广播消息
     */
    private void broadcastToTargets(BroadcastMessage message) {
        try {
            switch (message.getBroadcastType()) {
                case BROADCAST_TO_BATTLE:
                    broadcastToBattle(message);
                    break;
                case BROADCAST_TO_TEAM:
                    broadcastToTeam(message);
                    break;
                case SEND_TO_PLAYER:
                    sendToPlayer(message);
                    break;
                case BROADCAST_TO_ALL:
                    broadcastToAll(message);
                    break;
            }
            totalBroadcasted++;
            notifyBroadcasted(message);
        } catch (Exception e) {
            failedCount++;
            notifyBroadcastFailed(message, e);
        }
    }
    
    /**
     * 广播到所有战斗参与者
     * 
     * @param message 广播消息
     */
    private void broadcastToBattle(BroadcastMessage message) {
        long battleId = message.getBattleId();
        
        // 向所有连接的玩家发送消息
        for (BattlePlayerConnection conn : playerConnections.values()) {
            if (conn.getBattleId() == battleId && conn.isConnected()) {
                sendMessageToConnection(conn, message);
            }
        }
    }
    
    /**
     * 广播到特定队伍
     * 
     * @param message 广播消息
     */
    private void broadcastToTeam(BroadcastMessage message) {
        long battleId = message.getBattleId();
        int teamId = message.getTeamId();
        
        for (BattlePlayerConnection conn : playerConnections.values()) {
            if (conn.getBattleId() == battleId && conn.getTeamId() == teamId && conn.isConnected()) {
                sendMessageToConnection(conn, message);
            }
        }
    }
    
    /**
     * 发送消息给特定玩家
     * 
     * @param message 广播消息
     */
    private void sendToPlayer(BroadcastMessage message) {
        long playerId = message.getTargetPlayerId();
        BattlePlayerConnection conn = playerConnections.get(playerId);
        
        if (conn != null && conn.isConnected()) {
            sendMessageToConnection(conn, message);
        }
    }
    
    /**
     * 广播到所有连接
     * 
     * @param message 广播消息
     */
    private void broadcastToAll(BroadcastMessage message) {
        for (BattlePlayerConnection conn : playerConnections.values()) {
            if (conn.isConnected()) {
                sendMessageToConnection(conn, message);
            }
        }
    }
    
    /**
     * 向连接发送消息
     * 
     * @param connection 玩家连接
     * @param message 广播消息
     */
    private void sendMessageToConnection(BattlePlayerConnection connection, BroadcastMessage message) {
        if (connection != null && connection.isConnected()) {
            try {
                connection.sendMessage(message);
            } catch (Exception e) {
                // 记录发送失败
                failedCount++;
            }
        }
    }
    
    /**
     * 添加玩家连接
     * 
     * @param playerId 玩家ID
     * @param connection 玩家连接
     */
    public void addPlayerConnection(long playerId, BattlePlayerConnection connection) {
        if (connection != null) {
            playerConnections.put(playerId, connection);
            notifyConnectionAdded(playerId, connection);
        }
    }
    
    /**
     * 移除玩家连接
     * 
     * @param playerId 玩家ID
     */
    public void removePlayerConnection(long playerId) {
        BattlePlayerConnection removed = playerConnections.remove(playerId);
        if (removed != null) {
            notifyConnectionRemoved(playerId, removed);
        }
    }
    
    /**
     * 获取队列统计信息
     * 
     * @return 统计字符串
     */
    public String getQueueStatistics() {
        return broadcastQueue.getStatistics();
    }
    
    /**
     * 获取广播统计信息
     * 
     * @return 统计字符串
     */
    public String getBroadcasterStatistics() {
        return String.format("MessageBroadcaster{id=%s, totalBroadcasted=%d, failed=%d, connections=%d}",
                           broadcasterId, totalBroadcasted, failedCount, playerConnections.size());
    }
    
    /**
     * 添加监听器
     * 
     * @param listener 监听器
     */
    public void addListener(BroadcasterListener listener) {
        if (listener != null) {
            listeners.add(listener);
        }
    }
    
    /**
     * 移除监听器
     * 
     * @param listener 监听器
     */
    public void removeListener(BroadcasterListener listener) {
        listeners.remove(listener);
    }
    
    private void notifyBroadcasted(BroadcastMessage message) {
        for (BroadcasterListener listener : listeners) {
            listener.onMessageBroadcasted(message);
        }
    }
    
    private void notifyBroadcastFailed(BroadcastMessage message, Exception e) {
        for (BroadcasterListener listener : listeners) {
            listener.onBroadcastFailed(message, e);
        }
    }
    
    private void notifyConnectionAdded(long playerId, BattlePlayerConnection connection) {
        for (BroadcasterListener listener : listeners) {
            listener.onConnectionAdded(playerId, connection);
        }
    }
    
    private void notifyConnectionRemoved(long playerId, BattlePlayerConnection connection) {
        for (BroadcasterListener listener : listeners) {
            listener.onConnectionRemoved(playerId, connection);
        }
    }
    
    private void notifyError(Exception e) {
        for (BroadcasterListener listener : listeners) {
            listener.onError(e);
        }
    }
    
    /**
     * 广播器监听器接口
     */
    public interface BroadcasterListener {
        void onMessageBroadcasted(BroadcastMessage message);
        void onBroadcastFailed(BroadcastMessage message, Exception e);
        void onConnectionAdded(long playerId, BattlePlayerConnection connection);
        void onConnectionRemoved(long playerId, BattlePlayerConnection connection);
        void onError(Exception e);
    }
}
